package com.xhj.bigfactory.bigFactory.Lock;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * -
 *
 * @author 周沫 @Date 2021-07-29 @Time 22:50
 */
public class ReadWriteLockDemo {

  public static void main(String[] args) {
    MyCache myCache = new MyCache();
    new Thread(
            () -> {
              for (int i = 0; i < 10; i++) {
                myCache.put(String.valueOf(i), i);
              }
            },
            "AAA")
        .start();
    new Thread(
            () -> {
              myCache.get("qwer");
            },
            "BBB")
        .start();
    new Thread(
            () -> {
              myCache.get("qwer");
            },
            "CCC")
        .start();
    new Thread(
            () -> {
              myCache.get("qwer");
            },
            "DDD")
        .start();
    new Thread(
            () -> {
              try {
                Thread.sleep(2500);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
              myCache.get("qwer");
            },
            "EEE")
        .start();
  }

  static class MyCache {

    private volatile Map<String, Integer> map = new HashMap<>();

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void put(String key, Object value) {
      lock.writeLock().lock();
      System.out.println(Thread.currentThread().getName() + "正在写入，key:" + key + ", value:" + value);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + "写入完成");
      lock.writeLock().unlock();
    }

    public Object get(String key) {
      lock.readLock().lock();
      System.out.println(Thread.currentThread().getName() + "正在读取- - - ");
      int time = new Random().nextInt(2000);
      Integer value = map.get(key);
      try {
        Thread.sleep(time);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(
          Thread.currentThread().getName() + "读取完成, 用时" + time + "millis,  value:" + value);
      lock.readLock().unlock();
      return value;
    }
  }
}

class MyCache {

  private volatile Map<String, Integer> map = new HashMap<>();

  private Lock lock = new ReentrantLock();

  public void put(String key, Object value) {
    lock.lock();
    System.out.println(Thread.currentThread().getName() + "正在写入，key:" + key + ", value:" + value);
    try {
      Thread.sleep(500);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "写入完成");
    lock.unlock();
  }

  public Object get(String key) {
    System.out.println(Thread.currentThread().getName() + "正在读取- - - ");
    int time = new Random().nextInt(2000);
    Integer value = map.get(key);
    try {
      Thread.sleep(time);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(
        Thread.currentThread().getName() + "读取完成, 用时" + time + "millis,  value:" + value);
    return value;
  }
}
